﻿using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Scripting;
using Microsoft.Scripting.Ast;
using Microsoft.Linq.Expressions;

namespace DlrBasic.Parser.Ast
{
    class Def : Statement
    {
        VariableOrCall function;
        DlrBasicExpression body;

        public Def(SourceSpan span, VariableOrCall function, DlrBasicExpression body)
            : base(span)
        {
            ValidateFunctionName(function);
            this.function = function;
            this.body = body;
        }

        private void ValidateFunctionName(VariableOrCall function)
        {
            if (function.ArgumentsCount < 1) throw new ArgumentException("Invalid number of arguments for user function");
            
        }

        protected internal override Expression Generate(DlrBasicGenerator generator, StateMemberGenerator stateParameter, LambdaBuilder builder)
        {
            string name = function.Name.ToUpperInvariant();
            Type returnType = function.GetVariableType(generator);

            string[] parameterNames;
            Type[] parameterTypes;
            function.GenerateFunctionParameters(generator, out parameterNames, out parameterTypes);

            FunctionParameter[] parameters = new FunctionParameter[parameterNames.Length];
            for (int i = 0; i < parameters.Length; i++)
			{
                FunctionParameter param = new FunctionParameter();
                param.Name = parameterNames[i].ToUpperInvariant();
                param.Type = parameterTypes[i];
                parameters[i] = param;			 
			}

            LambdaExpression functionExpression = generator.CreateFunction(returnType, name, parameters,
                body);

            Expression register = Expression.Call(stateParameter.GetUserFunctionsVariable(),
                typeof(Runtime.DlrBasicUserFunctions).GetMethod("SetFunction"),
                Utils.Constant(name), 
                Expression.ConvertHelper(functionExpression, typeof(Delegate)));
                
            return Expression.Block(
                register, base.Generate(generator, stateParameter, builder));
        }
    }
}
